package actionEvent

import (
	"fmt"
	"strings"
)

type handler func(a ...interface{})
type limitHandler func(a ...interface{}) bool

type Param map[string]string

type Action struct {
	ActionName string
	Params     []map[string]string
}

type dispatcher struct {
	handlers      map[string]handler
	limitHandlers map[string]limitHandler
}

var d dispatcher

func init() {
	d.handlers = make(map[string]handler)
	d.limitHandlers = make(map[string]limitHandler)
}

func (this *dispatcher) Register(msgName string, h handler) {
	_, ok := this.handlers[msgName]
	if ok {
		return
	}
	this.handlers[msgName] = h
}

func (this *dispatcher) LimitRegister(msgName string, h limitHandler) {
	_, ok := this.limitHandlers[msgName]
	if ok {
		return
	}
	this.limitHandlers[msgName] = h
}

func (this *dispatcher) DoActionEvent(name string, arg ...interface{}) {
	handler, ok := this.handlers[name]
	if ok {
		handler(arg...)
	}
}

func (this *dispatcher) DoLimitActionEvent(name string, arg ...interface{}) bool {
	handler, ok := this.limitHandlers[name]
	if ok {
		return handler(arg...)
	}
	return false
}

func eliminate(str string, e string) string {
	str_ := []byte(str)
	e_ := []byte(e)
	out := []byte{}

	f := func(c byte) bool {
		for _, v := range e_ {
			if c == v {
				return false
			}
		}
		return true
	}

	for _, v := range str_ {
		if f(v) {
			out = append(out, v)
		}
	}
	return string(out)
}

func Analysis(str string) []Action {

	str = eliminate(str, "\r\t\n ")

	ret := []Action{}

	s1 := strings.Split(str, "#")
	if len(s1) == 1 && "" == s1[0] {
		return ret
	} else {
		for i := 0; i < len(s1); i++ {
			if s1[i] == "" {
				continue
			}

			action := Action{}

			s2 := strings.Split(s1[i], "(")

			if 2 != len(s2) {
				panic(fmt.Sprintf("invaild actionEvent:%s", str))
			}

			if "" == s2[0] {
				panic(fmt.Sprintf("invaild actionEvent:%s", str))
			}

			action.ActionName = s2[0]

			//fmt.Println(action.ActionName)

			s3 := strings.Split(s2[1], ")")

			if len(s3) > 0 && s3[0] != "" {
				action.Params = []map[string]string{}
				s4 := strings.Split(s3[0], ";")
				for _, v := range s4 {
					if "" == v {
						panic(fmt.Sprintf("invaild actionEvent:%s", str))
					}

					st := map[string]string{}

					s5 := strings.Split(v, ",")
					var id int = 1
					for _, vv := range s5 {
						idToStr := fmt.Sprintf("%d", id)
						st[idToStr] = vv
						id++
					}
					action.Params = append(action.Params, st)
				}
			}
			ret = append(ret, action)
		}
	}
	return ret
}

func Register(msgName string, h handler) {
	d.Register(msgName, h)
}
func LimitRegister(msgName string, h limitHandler) {
	d.LimitRegister(msgName, h)
}

func DoActionEvent(name string, arg ...interface{}) {
	d.DoActionEvent(name, arg...)
}

func DoLimitActionEvent(name string, arg ...interface{}) bool {
	return d.DoLimitActionEvent(name, arg...)
}
